<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Ice Stark Data-Event</title>
  </head>
  <body>
    <p>
      ice-stark-data 的 event 方案，源码尝试
      <a
        href="https://micro-frontends.ice.work/docs/guide/advanced/communication/"
        target="_blank"
        >ice-stark-data 方案地址</a
      >
    </p>
    <div>
      <button id="listenOn" style="margin-right: 8px">emit on</button>
      <button id="listenOff" style="margin-right: 8px">emit off</button>
      <button id="testEmit">emit event</button>
    </div>
    <p id="messageRecieved"></p>
    <script>
      // 注册 window 全局对象
      const namespace = "NEVINS";

      const setCache = (key, value) => {
        if (!window[namespace]) {
          console.log(`初始化 window 全局对象 ${namespace}`);
          window[namespace] = {};
        }
        window[namespace][key] = value;
      };

      const getCache = (key) => {
        const data = window[namespace];
        return data && data[key] ? data[key] : null;
      };

      // 判断是否为对象，为啥不直接用 typeof
      // 可能是为了兼容 IE 吧
      function isObject(o) {
        return Object.prototype.toString.call(o) === "[object Object]";
      }

      function isArray(a) {
        return Object.prototype.toString.call(a) === "[object Array]";
      }

      function warn(message) {
        return console && console.warn(message);
      }

      const randomString = (len) => {
        let chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz123456789";
        let strLen = chars.length;
        let randomStr = "";
        for (let i = 0; i < len; i++) {
          randomStr += chars.charAt(Math.floor(Math.random() * strLen));
        }
        return randomStr;
      };
    </script>
    <script>
      // 构建了一个 Event 类
      class Event {
        constructor() {
          this.eventEmitter = {};
        }

        emit(key, ...args) {
          const keyEmitter = this.eventEmitter[key];
          if (
            !isArray(keyEmitter) ||
            (isArray(keyEmitter) && keyEmitter.length === 0)
          ) {
            warn(`event.emit: no callback is called for ${String(key)}`);
            return;
          }

          // 通过回调把传入的参数值都传出去
          keyEmitter.forEach((cb) => {
            cb(...args);
          });
        }

        // 事件监听
        on(key, callback) {
          if (typeof key !== "string" && typeof key !== "symbol") {
            warn("event.on: key should be string / symbol");
            return;
          }
          if (callback === undefined || typeof callback !== "function") {
            warn("event.on: callback is required, should be function");
            return;
          }
          // 初始化事件 emit 队列 → 空数组
          if (!this.eventEmitter[key]) {
            this.eventEmitter[key] = [];
          }
          console.log(`开始监听${key}事件`);
          this.eventEmitter[key].push(callback);
        }

        has(key) {
          const keyEmitter = this.eventEmitter[key];
          return isArray(keyEmitter) && keyEmitter.length > 0;
        }

        off(key, callback) {
          if (typeof key !== "string" && typeof key !== "symbol") {
            warn("event.off: key should be string / symbol");
            return;
          }

          // 该事件没有回调函数
          if (!isArray(this.eventEmitter[key])) {
            warn(`event.off: ${String(key)} has no callback`);
            return;
          }

          if (callback === undefined) {
            this.eventEmitter[key] = undefined;
            return;
          }

          // 删除已经注册的回调函数
          console.log(`取消监听${key}事件`);
          this.eventEmitter[key] = this.eventEmitter[key].filter(
            (cb) => cb !== callback
          );
        }
      }

      // 在 NEVINS 全局变量下，注册 event key
      const eventNameSpace = "event";
      let event = getCache(eventNameSpace);
      if (!event) {
        event = new Event();
        setCache(eventNameSpace, event);
      }
    </script>
    <script>
      // 展示消息
      const showMessage = (val) => {
        console.log(`I recieved your message:${val}`);
        messageShow.textContent = `recieved message:${val}`;
      };
      // 注册回调函数，接收消息
      const listenOn = document.querySelector("#listenOn");
      const messageShow = document.querySelector("#messageRecieved");
      listenOn.addEventListener("click", () => {
        event.on("freshMessage", showMessage);
      });

      // 取消回调函数注册
      const listenOff = document.querySelector("#listenOff");
      listenOff.addEventListener("click", () => {
        event.off("freshMessage", showMessage);
      });

      // 触发 emit
      let message = "";
      const testEmit = document.querySelector("#testEmit");
      testEmit.addEventListener("click", () => {
        message = randomString(10);
        event.emit("freshMessage", message);
        testEmit.textContent = `emit event freshMessage:${message}`;
      });
    </script>
  </body>
</html>
